import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, In } from 'typeorm';
import { SysDept } from '../../entities/sys-dept.entity';
import { CreateDeptDto } from './dto/create-dept.dto';
import { UpdateDeptDto } from './dto/update-dept.dto';
import { DeptQuery } from './dto/query-dept.dto';

@Injectable()
export class DeptService {
  constructor(
    @InjectRepository(SysDept)
    private deptRepository: Repository<SysDept>,
  ) {}

  /**
   * 创建部门
   */
  async create(createDeptDto: CreateDeptDto, userId: number): Promise<SysDept> {
    const { parent_id } = createDeptDto;
    let treePath = '0';

    // 如果有父级，需要获取父级的tree_path
    if (parent_id !== 0) {
      const parentDept = await this.deptRepository.findOne({
        where: { id: parent_id },
      });
      if (!parentDept) {
        throw new NotFoundException(`父部门ID为${parent_id}的部门不存在`);
      }
      treePath = `${parentDept.tree_path},${parent_id}`;
    }

    const dept = this.deptRepository.create({
      ...createDeptDto,
      tree_path: treePath,
      create_by: userId,
    });

    return this.deptRepository.save(dept);
  }

  /**
   * 更新部门
   */
  async update(updateDeptDto: UpdateDeptDto, userId: number): Promise<SysDept> {
    const { id, parent_id } = updateDeptDto;

    const existDept = await this.deptRepository.findOne({ where: { id } });
    if (!existDept) {
      throw new NotFoundException(`部门ID为${id}的部门不存在`);
    }

    let treePath = '0';
    // 如果有父级，需要获取父级的tree_path
    if (Number(parent_id) !== 0) {
      // 不能将部门的父级设置为自己或其子部门
      if (id === parent_id) {
        throw new Error('不能将部门的父级设置为自己');
      }

      const parentDept = await this.deptRepository.findOne({
        where: { id: parent_id },
      });
      if (!parentDept) {
        throw new NotFoundException(`父部门ID为${parent_id}的部门不存在`);
      }

      // 检查是否设置了子部门为父部门（避免循环）
      if (
        parentDept.tree_path.includes(`,${id},`) ||
        parentDept.tree_path === `0,${id}`
      ) {
        throw new Error('不能将子部门设置为父部门');
      }

      treePath = `${parentDept.tree_path},${parent_id}`;

    }

    // 明确指定要更新的字段，避免类型不匹配问题
    const updatedDept = {
      ...existDept,
      name: updateDeptDto.name || existDept.name,
      code: updateDeptDto.code || existDept.code,
      parent_id: Number(parent_id),
      tree_path: treePath,
      sort:
        updateDeptDto.sort !== undefined
          ? Number(updateDeptDto.sort)
          : existDept.sort,
      status:
        updateDeptDto.status !== undefined
          ? Number(updateDeptDto.status)
          : existDept.status,
      update_by: Number(userId),
    };

    return this.deptRepository.save(updatedDept);
  }

  /**
   * 查询部门树
   */
  async findTree(): Promise<any[]> {
    const allDepts = await this.deptRepository.find({
      where: { is_deleted: false },
      order: { sort: 'ASC' },
    });
    const tree = this.buildDeptTree(allDepts, 0);
    return tree;
  }

  /**
   * 构建部门树
   */
  private buildDeptTree(depts: SysDept[], parentId: number): any[] {
    return depts
      .filter((dept) => Number(dept.parent_id) === parentId)
      .map((dept) => ({
        id: dept.id,
        name: dept.name,
        code: dept.code,
        parent_id: dept.parent_id,
        tree_path: dept.tree_path,
        sort: dept.sort,
        status: dept.status,
        create_time: dept.create_time,
        children: this.buildDeptTree(depts, Number(dept.id)),
      }));
  }

  /**
   * 分页查询部门列表
   */
  async findByPage(
    query: DeptQuery,
  ): Promise<{ list: SysDept[]; total: number }> {
    const { page = 1, limit = 10, name, code, status, parent_id } = query;

    const where: any = { is_deleted: false };
    if (name) where.name = Like(`%${name}%`);
    if (code) where.code = Like(`%${code}%`);
    if (status !== undefined) where.status = status;
    if (parent_id !== undefined) where.parent_id = parent_id;

    const [list, total] = await this.deptRepository.findAndCount({
      where,
      skip: (page - 1) * limit,
      take: limit,
      order: { sort: 'ASC' },
    });

    return { list, total };
  }

  /**
   * 根据ID查询部门
   */
  async findById(id: number): Promise<SysDept> {
    const dept = await this.deptRepository.findOne({
      where: { id, is_deleted: false },
    });
    if (!dept) {
      throw new NotFoundException(`部门ID为${id}的部门不存在`);
    }
    return dept;
  }

  /**
   * 递归删除部门及其所有子部门
   * @param id 要删除的部门ID
   * @param userId 操作用户ID
   */
  async remove(id: number, userId: number): Promise<void> {
    const dept = await this.deptRepository.findOne({
      where: { id, is_deleted: false },
    });

    if (!dept) {
      throw new NotFoundException(`部门ID为${id}的部门不存在`);
    }

    // 获取当前部门及所有子部门的ID列表
    const deptIdsToDelete = await this.getAllChildDeptIds(id);

    // 包含自身ID
    deptIdsToDelete.push(id);

    // 批量逻辑删除部门
    await this.deptRepository.update(
      { id: In(deptIdsToDelete), is_deleted: false },
      {
        is_deleted: true,
        update_by: userId,
        update_time: new Date(), // 确保更新时间被更新
      },
    );
  }

  /**
   * 递归获取部门的所有子部门ID
   * @param parentId 父部门ID
   * @returns 子部门ID数组
   */
  private async getAllChildDeptIds(parentId: number): Promise<number[]> {
    const allChildIds: number[] = [];

    // 查询直接子部门
    const children = await this.deptRepository.find({
      where: { parent_id: parentId, is_deleted: false },
      select: ['id'],
    });

    // 如果没有子部门，返回空数组
    if (!children || children.length === 0) {
      return allChildIds;
    }

    // 提取子部门ID
    const childIds = children.map((child) => child.id);
    allChildIds.push(...childIds);

    // 递归查询每个子部门的子部门
    for (const childId of childIds) {
      const grandChildIds = await this.getAllChildDeptIds(childId);
      allChildIds.push(...grandChildIds);
    }

    return allChildIds;
  }

  /**
   * 获取部门选择列表(树形结构)
   */
  async getDeptOptions(): Promise<any[]> {
    const allDepts = await this.deptRepository.find({
      where: { is_deleted: false },
      order: { sort: 'ASC' },
    });
    return this.buildDeptOptions(allDepts, 0);
  }

  /**
   * 构建部门选项树 (value-label格式)
   */
  private buildDeptOptions(depts: SysDept[], parentId: number): any[] {
    return depts
      .filter((dept) => Number(dept.parent_id) === parentId)
      .map((dept) => {
        const children = this.buildDeptOptions(depts, Number(dept.id));
        const node: any = {
          value: dept.id.toString(), // 转成字符串，符合前端组件要求
          label: dept.name,
        };

        // 只有当有子部门时才添加children属性
        if (children && children.length > 0) {
          node.children = children;
        }

        return node;
      });
  }
}
